package it.infodea.tapestrydea.components.jcr;

import it.infodea.tapestrydea.services.jcr.JcrWorkspaceService;
import it.infodea.tapestrydea.services.jcr.nodes.wrappers.JcrFolderNode;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.jcr.AccessDeniedException;
import javax.jcr.ItemNotFoundException;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;

import org.apache.tapestry5.Asset;
import org.apache.tapestry5.ComponentEventCallback;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.annotations.IncludeStylesheet;
import org.apache.tapestry5.annotations.OnEvent;
import org.apache.tapestry5.annotations.Path;
import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.annotations.SetupRender;
import org.apache.tapestry5.internal.util.Holder;
import org.apache.tapestry5.ioc.annotations.Inject;

@IncludeStylesheet("FoldersNavigator.css")
public class FoldersNavigator {

	public static final String SELECT_FOLDER_EVENT = "selectFolder";
	private static final String INTERNAL_SELECT_FOLDER_EVENT_NAME = "foldersNavigator_selectFolder";

	@Inject
	@Path("classpath:/it/infodea/tapestrydea/components/jcr/folder.png")
	private Asset folderImage;
	
	@Inject
	@Path("classpath:/it/infodea/tapestrydea/components/jcr/folder_up.png")
	private Asset folderUpImage;
	
	@Persist
	private String path;

	@Property
	private JcrFolderNode selectedFolder;

	private JcrFolderNode folder;

	private List<JcrFolderNode> folders;
	
	@SuppressWarnings("unused")
	@Property
	private PathInfo pathItem;

	@Inject
	private ComponentResources _resources;

	@Inject
	private JcrWorkspaceService service;
	

	@SetupRender
	void setup() throws RepositoryException{
		if(path == null || "/".equals(path)){
			selectedFolder = service.getAdminRootNode();
			path = "/";
		}else{
			selectedFolder = service.getFolder(path);
		}
		folders = selectedFolder.getChilds();
	}
	
	@OnEvent(INTERNAL_SELECT_FOLDER_EVENT_NAME)
	Object changePath(String path) throws PathNotFoundException, RepositoryException{
		JcrFolderNode folder = service.getFolder(path);
		if(folder != null){
			selectedFolder = folder;
			this.path = path;
			return triggerEvent(selectedFolder);
		}
		return null;
	}
	
	private Object triggerEvent(JcrFolderNode selectedFolder){
		final Holder<Object> resultHolder = Holder.create();

		ComponentEventCallback<Object> handler = new ComponentEventCallback<Object>() {

			public boolean handleResult(Object result) {
				resultHolder.put(result.toString());
				return true;
			}
		};

		_resources.triggerEvent(SELECT_FOLDER_EVENT, new Object[] { selectedFolder },
				handler);
		
		return resultHolder.get();
	}
	
	public boolean isRoot(){
		return isRoot(path);
	}

	private boolean isRoot(String path){
		return path == null || "/".equals(path);
	}
	
	public List<JcrFolderNode> getFolders() {
		return folders;
	}

	public JcrFolderNode getFolder() {
		return folder;
	}

	public void setFolder(JcrFolderNode folder) {
		this.folder = folder;
	}

	public List<PathInfo> getPathNavigatorList() throws ItemNotFoundException, AccessDeniedException, RepositoryException {
		List<PathInfo> pathInfos = new ArrayList<PathInfo>();
		JcrFolderNode temp = selectedFolder;
		pathInfos.add(new PathInfo(temp.getName(), temp.getPath()));
		while(!temp.isRoot() && (temp = temp.getParent()) != null){
			pathInfos.add(new PathInfo(temp.getName(), temp.getPath()));
		}
		Collections.reverse(pathInfos);
		return pathInfos;
	}
	
	

	public static class PathInfo{
		private String name;
		private String path;
		public PathInfo(String name, String path) {
			super();
			this.name = name;
			this.path = path;
		}
		public String getName() {
			return name;
		}
		public String getPath() {
			return path;
		}
	}



	public Asset getFolderImage() {
		return folderImage;
	}

	public Asset getFolderUpImage() {
		return folderUpImage;
	}
}
